package com.software.zsrt;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class XmlSerializer {
	@SuppressWarnings("unused")
	public  void serialize(File file, Object obj) {
		try {
			if (!file.exists()) {
				file.getParentFile().mkdirs();
//				file.mkdirs();
//				file.createNewFile();
			}
			Class<?> clazz=obj.getClass();
			FileOutputStream fos=new FileOutputStream(file);
			OutputStreamWriter osw=new OutputStreamWriter(fos,"utf-8");
			BufferedWriter writer=new BufferedWriter(osw);
			writer.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
			writer.newLine();
			if(obj instanceof Collection){
				System.out.println("集合");
				writer.write(String.format("<%s type=\"%s\">\n","ArrayOfList",obj.getClass().getName()));
				Method iteratorMethod=clazz.getMethod("iterator");
				//遍历集合
				Iterator iterator=(Iterator)iteratorMethod.invoke(obj);
				while(iterator.hasNext()){
					//System.out.println(getXmlString(iterator.next()));
					writer.write(getXmlString(iterator.next()));
					writer.newLine();
				}
				writer.write("</ArrayOfList>");
			}else{
				System.out.println("单个对象");
				System.out.println(getXmlString(obj));
				writer.write(getXmlString(obj));
			}
			writer.flush();
			writer.close();
			osw.close();
			fos.close();
//			for(Class c:interfaces){
//				if(c.getName().equals("java.util.Collection")){
//					System.out.println("集合");
//					isList=true;
//					break;
//				}
//			}
//			if(!isList){
//				System.out.println("单个对象");
//			}else{
//				makeList(file, obj);
//			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private String getXmlString(Object obj){
		String xmlString="";
//		System.out.println(obj.getClass().getName());
//		System.out.println(getClassName(obj.getClass().getName()));
		String fullName=obj.getClass().getName();
		xmlString=String.format("<%s type=\"%s\">\n", getClassName(fullName),fullName);
		Field[] fields=obj.getClass().getDeclaredFields();
		for(Field field:fields){
			try {
				field.setAccessible(true);
				xmlString+=String.format("\t<%s>%s</%s>\n",field.getName(),field.get(obj),field.getName());
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		xmlString+=String.format("</%s>",getClassName(fullName));
		return xmlString;
	}
	
	private String getClassName(String fullName){
		return fullName.substring(fullName.lastIndexOf(".")+1);
	}
	
	private void makeList(File file,Object obj){
		Class<?> clazz=obj.getClass();
		FileOutputStream fos=null;
		OutputStreamWriter osw=null;
		BufferedWriter writer=null;
		try {
			Method sizeMethod=clazz.getMethod("size");
			int count=(Integer) sizeMethod.invoke(obj);
			System.out.println("大小："+count);
			fos=new FileOutputStream(file);
			osw=new OutputStreamWriter(fos, "utf-8");
			writer=new BufferedWriter(osw);
			writer.write("<?xml version=\"1.0\" encoding=\"utf-8\" ?>");
			writer.newLine();
			Method getMethod=clazz.getMethod("get", int.class);
			for(int i=0;i<count;i++){
				Object item=getMethod.invoke(obj, i);
				System.out.println(item);
			}
			writer.flush();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			try {
				writer.close();
				osw.close();
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			
		}
	}
	
	public <T> T deserialze(File file,Class<T> clazz){
		SAXReader reader=new SAXReader();
		T obj=null;
		try {
			obj=clazz.newInstance();
			Document doc=reader.read(file);
			Element root=doc.getRootElement();
			//检查类型
			if(root.getName().equals("ArrayOfList")){
				for(Iterator<Element>iterator=root.elementIterator();iterator.hasNext();){
					Element element=iterator.next();
					Class<?> itemClass=Class.forName(element.attributeValue("type"));
					Object item=itemClass.newInstance();
					readObject(item,element);
					Method addMethod=clazz.getMethod("add", Object.class);
					addMethod.invoke(obj, item);
				}
			}else{
				readObject(obj, root);
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return obj;
	}
	
	private  void readObject(Object obj,Element element) throws SecurityException, NoSuchFieldException{
		for(Iterator<Element> iterator=element.elementIterator();iterator.hasNext();){
			Element prop=iterator.next();
			Field field=obj.getClass().getDeclaredField(prop.getName());
			field.setAccessible(true);
			//field.set(obj, element.getText());
			setField(field, obj,prop.getText());
		}
	}
	
	private void setField(Field field,Object obj,String value){
		//System.out.println(field.getType().getName());
		Class<?> type=field.getType();
			try {
				if(type==String.class){
					field.set(obj, value);
				}else	if(type==int.class){
					field.setInt(obj, Integer.parseInt(value));
				}else if(type==double.class){
					field.setDouble(obj, Double.parseDouble(value));
				}
				//略
			} catch (NumberFormatException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		
	}

}
